package com.yoga.manager.admin.impl;

import com.yoga.common.appexception.AppErrorCodeEnum;
import com.yoga.common.appexception.AppException;
import com.yoga.common.bo.ClassTableBO;
import com.yoga.common.bo.CourseBO;
import com.yoga.common.page.PageBO;
import com.yoga.common.qto.ClassTableQTO;
import com.yoga.common.qto.CourseQTO;
import com.yoga.dao.dao.ClassTableDao;
import com.yoga.dao.dao.CourseDao;
import com.yoga.dao.dao.TeacherDao;
import com.yoga.dao.domain.ClassTableDO;
import com.yoga.dao.domain.CourseDO;
import com.yoga.dao.domain.TeacherDO;
import com.yoga.manager.admin.AdminClassTableManager;
import com.yoga.manager.beanUtil.ClassTableBeanUtil;
import com.yoga.manager.beanUtil.CourseBeanUtil;
import com.yoga.manager.uitl.DateStyle;
import com.yoga.manager.uitl.DateUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * Created by hdx on 2020/9/28.
 */
@Component
public class AdminClassTableManagerImpl implements AdminClassTableManager {
    Logger logger = LoggerFactory.getLogger(AdminClassTableManagerImpl.class);

    @Resource
    private ClassTableDao classTableDao;

    @Resource
    private CourseDao courseDao;

    @Resource
    private TeacherDao teacherDao;

    @Override
    public ClassTableBO addData(ClassTableBO classTableBO) throws AppException {
        if (classTableBO == null) {
            throw new AppException(AppErrorCodeEnum.PARAMETER_NULL);
        }
        if (classTableBO.getClassDate() == null) {
            throw new AppException(AppErrorCodeEnum.CLASS_DATE_NULL);
        }
        if (classTableBO.getClassType() == null) {
            throw new AppException(AppErrorCodeEnum.CLASS_TYPE_NULL);
        }
        if (classTableBO.getClassType() != 1 && classTableBO.getClassType() != 2) {
            throw new AppException(AppErrorCodeEnum.PARAM_ERROR);
        }
        if (classTableBO.getCourseId() == null) {
            throw new AppException(AppErrorCodeEnum.NOT_CHOICE);
        }
        if (classTableBO.getTeacherId() == null) {
            throw new AppException(AppErrorCodeEnum.TEACHER_NULL);
        }
        if (classTableBO.getAboutNumber() == null || classTableBO.getAboutNumber() <= 0) {
            throw new AppException(AppErrorCodeEnum.ABOUT_NUMBER_NULL);
        }
        if (classTableBO.getStartTime() == null || classTableBO.getEndTime() == null) {
            throw new AppException(AppErrorCodeEnum.TIME_NULL);
        }
        if (StringUtils.isEmpty(classTableBO.getTeacherName())) {
            throw new AppException(AppErrorCodeEnum.TEACHER_NULL);
        }
        if (classTableBO.getYogaShopId() == null) {
            throw new AppException(AppErrorCodeEnum.PARAMETER_NULL);
        }

        Date nowDate = DateUtil.dateFormat(new Date(), DateStyle.YYYY_MM_DD);
        classTableBO.setClassDate(DateUtil.dateFormat(classTableBO.getClassDate(), DateStyle.YYYY_MM_DD));
        if (classTableBO.getClassDate().getTime() < nowDate.getTime()) {
            throw new AppException(AppErrorCodeEnum.CLASS_DATE_BEFORE_DAY);
        }
        TeacherDO teacherDO = teacherDao.findById(classTableBO.getTeacherId());
        if (teacherDO == null) {
            throw new AppException(AppErrorCodeEnum.TEACHER_NOT_EXIST);
        }
        classTableBO.setTeacherName(teacherDO.getTeacherName());
        classTableBO.setTeacherImg(teacherDO.getTeacherImg());

        CourseDO courseDO = courseDao.findById(classTableBO.getCourseId());
        classTableBO.setCourseName(courseDO.getCourseName());
        classTableBO.setCourseLevel(courseDO.getCourseLevel());
        ClassTableDO classTableDO = ClassTableBeanUtil.classTableBOToDO(classTableBO);

        int num = classTableDao.insert(classTableDO);
        if (num <= 0) {
            throw new AppException(AppErrorCodeEnum.INSERT_DATA_NULL);
        }

        return ClassTableBeanUtil.classTableDOToBO(classTableDao.findById(classTableDO.getId()));
    }

    @Override
    public Boolean copyUpWeekClassTable(Long yogaShopId) throws AppException {
        if (yogaShopId == null) {
            throw new AppException(AppErrorCodeEnum.NOT_CHOICE_SHOP);
        }
        Date thisMonday = DateUtil.getThisWeekMonday();
        for (int i = 0; i < 7; i++) {
            int day = 7 - i;
            Date hisDay = DateUtil.addDay(thisMonday, -day);
            Date thisDay = DateUtil.addDay(thisMonday, i);
            ClassTableQTO qto = new ClassTableQTO();
            qto.setNeedPaging(false);
            qto.setYogaShopId(yogaShopId);
            qto.setClassDate(hisDay);
            List<ClassTableDO> doList = classTableDao.findForPage(qto);
            if (!CollectionUtils.isEmpty(doList)) {
                doList.stream().forEach(classTableDO -> {classTableDO.setId(null);classTableDO.setClassDate(thisDay);});
            }
            addList(doList);
        }

        return Boolean.TRUE;
    }

    @Override
    public Boolean copy2NextWeek(Long yogaShopId) throws AppException {
        if (yogaShopId == null) {
            throw new AppException(AppErrorCodeEnum.NOT_CHOICE_SHOP);
        }
        Date thisMonday = DateUtil.getThisWeekMonday();
        Date nextMonday = DateUtil.getNextWeekMonday();
        for (int i = 0; i < 7; i++) {
            int day = 7 - i;
            Date thisDay = DateUtil.addDay(thisMonday, i);
            Date nextDay = DateUtil.addDay(nextMonday, i);
            ClassTableQTO qto = new ClassTableQTO();
            qto.setNeedPaging(false);
            qto.setYogaShopId(yogaShopId);
            qto.setClassDate(thisDay);
            List<ClassTableDO> doList = classTableDao.findForPage(qto);
            if (!CollectionUtils.isEmpty(doList)) {
                doList.stream().forEach(classTableDO -> {classTableDO.setId(null);classTableDO.setClassDate(nextDay);});
            }
            addList(doList);
        }


        return true;
    }

    private Boolean addList(List<ClassTableDO> doList) {
        int num = classTableDao.insertList(doList);
        if (num <= 0) {
            throw new AppException(AppErrorCodeEnum.INSERT_DATA_NULL);
        }

        return true;
    }

    @Override
    public Boolean updateData(ClassTableBO classTableBO) throws AppException {
        if (classTableBO == null || classTableBO.getClassTableId() == null) {
            throw new AppException(AppErrorCodeEnum.PARAMETER_NULL);
        }
        if (classTableBO.getClassDate() != null) {
            Date nowDate = DateUtil.dateFormat(new Date(), DateStyle.YYYY_MM_DD);
            classTableBO.setClassDate(DateUtil.dateFormat(classTableBO.getClassDate(), DateStyle.YYYY_MM_DD));
            if (classTableBO.getClassDate().getTime() < nowDate.getTime()) {
                throw new AppException(AppErrorCodeEnum.CLASS_DATE_BEFORE_DAY);
            }
        }
        ClassTableDO update = ClassTableBeanUtil.classTableBOToDO(classTableBO);
        int num = classTableDao.updateById(update);
        if (num <= 0) {
            throw new AppException(AppErrorCodeEnum.UPDATE_DATA_NULL);
        }

        return Boolean.TRUE;
    }

    @Override
    public Boolean deleteData(Long classTableId) throws AppException {
        if (classTableId == null) {
            throw new AppException(AppErrorCodeEnum.PARAMETER_NULL);
        }
        int num = classTableDao.deleteById(classTableId);
        if (num <= 0) {
            throw new AppException(AppErrorCodeEnum.UPDATE_DATA_NULL);
        }

        return Boolean.TRUE;
    }

    @Override
    public PageBO<ClassTableBO> findForPage(ClassTableQTO classTableQTO) throws AppException {
        if (classTableQTO == null) {
            throw new AppException(AppErrorCodeEnum.PARAMETER_NULL);
        }
        if (classTableQTO.getYogaShopId() == null) {
            throw new AppException(AppErrorCodeEnum.NOT_SHOP_CHORES);
        }
        if (classTableQTO.getClassDate() != null) {
            classTableQTO.setClassDate(DateUtil.dateFormat(classTableQTO.getClassDate(), DateStyle.YYYY_MM_DD));
        }
        if (classTableQTO.getClassDate() == null) {
            classTableQTO.setStartDate(DateUtil.dateFormat(new Date(), DateStyle.YYYY_MM_DD));
        }
        PageBO<ClassTableBO> pageBO = new PageBO<>();
        pageBO.setQuery(classTableQTO);
        Integer count = classTableDao.findForPageCount(classTableQTO);
        if (count == null || count <= 0) {
            return pageBO;
        }
        List<ClassTableBO> boList = ClassTableBeanUtil.doList2BOList(classTableDao.findForPage(classTableQTO));
        if (CollectionUtils.isEmpty(boList)) {
            return pageBO;
        }
        List<Long> courseIds = new ArrayList<>(boList.stream().map(ClassTableBO::getCourseId).collect(Collectors.toSet()));
        if (!CollectionUtils.isEmpty(courseIds)) {
            CourseQTO courseQTO = new CourseQTO();
            courseQTO.setCourseIds(courseIds);
            courseQTO.setNeedPaging(false);
            List<CourseBO> courseBOs = CourseBeanUtil.doList2BOList(courseDao.findForPage(courseQTO));
            if (!CollectionUtils.isEmpty(courseBOs)) {
                Map<Long, CourseBO> courseBOMap = courseBOs.stream().collect(Collectors.toMap(CourseBO::getCourseId, Function.identity()));
                if (!CollectionUtils.isEmpty(courseBOMap))
                    boList.stream().filter(classTableBO -> classTableBO.getCourseId() != null && courseBOMap.containsKey(classTableBO.getCourseId()))
                            .forEach(classTableBO -> classTableBO.setCourseBO(courseBOMap.get(classTableBO.getCourseId())));
            }
        }

        pageBO.setTotalCount(count);
        pageBO.setData(boList);

        return pageBO;
    }

    @Override
    public PageBO<Map<Date, List<ClassTableBO>>> findForPageWeekGroup(ClassTableQTO classTableQTO) throws AppException {
        if (classTableQTO == null) {
            throw new AppException(AppErrorCodeEnum.PARAMETER_NULL);
        }
        if (classTableQTO.getYogaShopId() == null) {
            throw new AppException(AppErrorCodeEnum.NOT_CHOICE_SHOP);
        }
        if (classTableQTO.getWeekType() == null) {
            throw new AppException(AppErrorCodeEnum.PARAMETER_NULL);
        }
        if (classTableQTO.getClassType() == null) {
            throw new AppException(AppErrorCodeEnum.PARAMETER_NULL);
        }
        if (classTableQTO.getClassType() != 1 && classTableQTO.getClassType() != 2) {
            throw new AppException(AppErrorCodeEnum.PARAM_ERROR);
        }
        if (classTableQTO.getWeekType() == 0) { //本周
            classTableQTO.setStartDate(DateUtil.getThisWeekMonday());
            classTableQTO.setEndDate(DateUtil.addDay(DateUtil.getThisWeekSunday(), 1));
        } else if (classTableQTO.getWeekType() == 1) { //下一周
            classTableQTO.setStartDate(DateUtil.getNextWeekMonday());
            classTableQTO.setEndDate(DateUtil.addDay(DateUtil.getNextWeekSunday(), 1));
        }
        PageBO<Map<Date, List<ClassTableBO>>> pageBO = new PageBO<>();
        pageBO.setQuery(classTableQTO);
        Integer count = classTableDao.findForPageCount(classTableQTO);
        if (count == null || count <= 0) {
            return pageBO;
        }
        List<Map<Date, List<ClassTableBO>>> result = new ArrayList<>();
        Map<Date, List<ClassTableBO>> resultMap = new HashMap<>();
        List<ClassTableBO> boList = ClassTableBeanUtil.doList2BOList(classTableDao.findForPage(classTableQTO));
        if (!CollectionUtils.isEmpty(boList)) {
            Map<Date, List<ClassTableBO>> boMap = boList.stream().collect(Collectors.groupingBy(ClassTableBO::getClassDate));
            resultMap = boMap.entrySet().stream().sorted(Map.Entry.comparingByKey())
                    .collect(
                            Collectors.toMap(
                                    Map.Entry::getKey,
                                    Map.Entry::getValue,
                                    (oldVal, newVal) -> oldVal,
                                    LinkedHashMap::new
                            ));
            result.add(resultMap);
        }

        pageBO.setTotalCount(count);
        pageBO.setData(result);

        return pageBO;
    }

}
